# Author: Darren Colby
# Date: 10/4/2021
# Purpose: To provide helper functions for the main script

# plot_network ------------------------------------------------------------


# Function for plotting a network
# @Params: network, an igraph object; subtitle, a subtitle for the plot
# @Returns: A ggraph object of the network
plot_network <- function(network, subtitle){
   
   graph <- ggraph(network,
                   layout = "kk") +
      geom_edge_link(arrow = arrow(length = unit(2, "mm")),
                     end_cap = circle(1.5, "mm"),
                     color = "gray30") + 
      geom_node_point(aes(color = as.factor(role) %>% 
                             fct_relevel("Small Cartels and Militias", 
                                         after = 3)),
                      size = 3) +   
      labs(subtitle = subtitle,
           color = "Role") + 
      scale_color_gdocs() + 
      theme_graph() + 
      theme(text = element_text(family= "serif", size = 16),
            plot.subtitle = element_text(family = "serif", size = 16),
            legend.title = element_text(family = "serif", size = 16))
   
   return(graph)
}


# plot_degree_distribution ------------------------------------------------


# Function for plotting the degree distribution of a network
# @Params: graph, an igraph object; mode, in for in-degree and out for 
# out-degree; subtitle, a subtitle for the plot; xlab, a label for the x-axis; 
# limits, used to expand the y-axis
# @Returns: A ggplot object showing the degree distribution of a network
plot_degree_distribution <- function(graph, mode, subtitle, xlab, limits){
   
   return(as_tibble(degree(graph, mode = mode)) %>% 
             rename("degree" = value) %>% 
             group_by(degree) %>% 
             summarise(count = n()) %>% 
             ungroup() %>% 
             ggplot(aes(x = as.factor(degree),
                        y = count)) +  
             scale_y_continuous(expand = c(0, 0), 
                                limits = limits) + 
             scale_x_discrete(expand = c(0, 0.5)) + 
             geom_col() + 
             labs(subtitle = subtitle,
                  x = xlab,
                  y = "Count") + 
             geom_text(aes(label = count),
                       vjust = -0.5) + 
             theme_few())
}

# estimate_saom -----------------------------------------------------------

# Function to estimate a stochastic actor oriented model
# @Params: effect, the effect to estimate; seed, the seed to set the machine to
# @Returns: A sienaFit object
estimate_saom <- function(effect, seed){
   
   effect <- deparse(substitute(effect))
   
   # Create the basic data
   data <- sienaDataCreate(dv, aggression_var, subfaction_var, militia_var, 
                           role_var, joiners)
   
   # Effects for rate, reciprocity, and out-degree
   effects <- getEffects(data)
   
   # Effects for in-degree popularity, in-degree activity, out-degree popularity,
   # and balance. These reflect preferential attachment and similarity for outgoing 
   # ties between actors
   if (effect == "Jout") effects <- includeEffects(effects, Jout)
   if (effect == "inPop") effects <- includeEffects(effects, inPop)
   if (effect == "outInAss") effects <- includeEffects(effects, outInAss)
   if (effect == "transTrip1") effects <- includeEffects(effects, transTrip1)
   
   # Effects for homophily
   effects <- includeEffects(effects, sameX, interaction1 = "aggression_var")
   effects <- includeEffects(effects, sameX, interaction1 = "subfaction_var")
   effects <- includeEffects(effects, sameX, interaction1 = "militia_var")
   effects <- includeEffects(effects, sameX, interaction1 = "role_var")
   
   # Define algorithm and get results
   algorithm <- sienaAlgorithmCreate(projname = "output", seed = seed, 
                                     n3 = 3000, nsub = 7, firstg = 0.01)
   results <- siena07(algorithm, data = data, effects = effects, 
                      returnDeps = TRUE)
   
   # Check for convergence
   if (max(results$tstat > 1) | abs(results$tconv.max) > 0.25){
      
      results <- siena07(algorithm, data = data, effects = effects, 
                         returnDeps = TRUE, prevAns = results)
      
   }
   
   return(results)
   
}


# plot_importance ---------------------------------------------------------


# Function to plot the difference of relative importance scores of effects
# between the first and second networks.
# @Params: results; a sienaFit object; effect, the name of the effect of
# interest; title, a title for the plot; subtitle, a subtitle for the plot
# @Returns: A ggplot2 object
plot_importance <- function(results, effect, subtitle){
   
   # Creates a sienaData object
   data <- sienaDataCreate(dv, aggression_var, subfaction_var, militia_var, 
                           role_var, joiners)
   
   # Vectors for the mean relative importance for each effect in both periods
   before <- sienaRI(data, results)[[4]][1] %>% unlist()
   after <- sienaRI(data, results)[[4]][2] %>% unlist()
   
   # Creates a vector for statistical significance
   signif <- plotreg(results)[[1]][10][-1, ] %>% unlist()
   
   # A vector of effect names
   effect_names <- plotreg(results)[[1]][1][-1, ] %>% unlist()
   
   # Creates a tibble of effect names, difference in relative importance and
   # statistical significance
   before_after_df <- bind_cols(effect_names, before, after, signif) %>% 
      rename(effect = "...1", before = "...2", after = "...3", signif = "...4") %>% 
      mutate(dif = after - before) %>% 
      ungroup()
   
   plot <- ggplot(data = before_after_df) + 
      geom_point(aes(x = before,
                     y = effect,
                     color = signif)) + 
      geom_segment(aes(x = before,
                       xend = after,
                       y = effect,
                       yend = effect,
                       color = signif),
                   arrow = arrow(length = unit(2, "mm"), 
                                 type = "closed")) + 
      scale_y_discrete(labels = c("Role\nsimilarity", "Militia\nsimilarity",
                                  "Subfaction\nsimilarity", 
                                  "Aggression\nsimilarity", 
                                  effect, "Reciprocity", 
                                  "Rate")) +
      
      # Statistically significant variables are red
      scale_color_manual(values = c("black", "red")) +
      labs(subtitle = subtitle,
           x = "Mean relative importance",
           y = NULL) +  
      geom_text(aes(x = (before + after)/2,
                    y = effect,
                    label = round(dif, 3)),
                vjust = -0.5,
                hjust = 0.5) + 
      theme_few() + 
      theme(legend.position = "none")
   
   return(plot)
   
}
